📦 BAB 9 • SEMESTER 2

DATABASE MODERN

dengan Laravel & MySQL

DB
SQL
ORM
MVC
API
Web

Pelajari cara merancang database profesional, menulis query efisien, dan mengintegrasikan dengan Laravel untuk membangun aplikasi web yang scalable.

💡 Gunakan tombol panah atau keyboard untuk navigasi

📚 TUJUAN

Apa yang akan kamu kuasai?

  • Memahami konsep database relasional dan normalisasi
  • Merancang Entity-Relationship Diagram (ERD) yang efisien
  • Membuat migration dan seeder di Laravel
  • Menggunakan Eloquent ORM untuk CRUD operasi
  • Mengelola relasi database: One-to-One, One-to-Many, Many-to-Many
  • Menulis query yang optimal dengan eager loading
  • Membangun aplikasi web dengan arsitektur MVC yang sesuai

🎯 By the end of this chapter, kamu akan bisa membangun Product Management System dengan fitur CRUD lengkap, relasi database kompleks, dan upload gambar!

🏗️ KONSEP DASAR

Apa itu Database?

Database = Perpustakaan Digital

Database adalah tempat penyimpanan data terstruktur. Bayangkan database seperti perpustakaan sekolahmu:

  • Buku = Baris data
  • Rak = Tabel
  • Kategori buku = Schema
  • Nomor induk buku = Primary Key
  • Pencarian katalog = Query

📚

Saat kamu cari buku "Pemrograman Web", perpustakaan tidak cari satu per satu. Ada katalog (INDEX) yang menunjuk langsung ke lokasi buku!

💡 Begitu juga database: gunakan INDEX dan PRIMARY KEY untuk pencarian ultra-cepat!

🔧 BUILDING BLOCKS

Komponen Utama Database

1. Table (Tabel)

Kumpulan data dalam format baris dan kolom, seperti spreadsheet Excel.

2. Row / Record (Baris)

Satu entitas data. Contoh: 1 siswa = 1 baris di tabel students.

3. Column / Field (Kolom)

Atribut data. Contoh: nama, email, nomor induk siswa adalah kolom-kolom di tabel students.

4. Primary Key

Identitas unik setiap baris. Tidak boleh ada 2 siswa dengan ID yang sama!

5. Foreign Key

Penghubung antar tabel. Contoh: kolom course_id di tabel enrollments menunjuk ke tabel courses.

6. Index

Akselerasi pencarian. Seperti katalog perpustakaan, membuat query 100x lebih cepat!

👥 ANALOGI

Tabel Database = Meja Absen Kelas

Perhatikan meja absen di kelas kamu:

Struktur Meja Absen:

  • Nama kolom: No, Nama, Tanggal, Status
  • Baris pertama: Header (deskripsi kolom)
  • Baris berikutnya: Data siswa (primary key = No urut)
  • Sel: Setiap data (nama = "Rifqi", status = "Hadir")

Di Database (SQL):

  • Kolom: id, name, date, status
  • Tipe data: INT, VARCHAR, DATE, ENUM
  • Primary Key: id (unik, tidak boleh kosong)
  • Index: Percepatan pencarian siswa by name

✨ Meja absen fisik = Tabel database digital!

📐 DESIGN

Database Design & Entity-Relationship Diagram

ERD adalah blueprint database — diagram yang menunjukkan tabel dan relasi antar tabel.

erDiagram STUDENT ||--o{ ENROLLMENT : "takes" COURSE ||--o{ ENROLLMENT : "has" STUDENT { int student_id PK string name string email date created_at } COURSE { int course_id PK string title string description int credits } ENROLLMENT { int enrollment_id PK int student_id FK int course_id FK string grade }

Penjelasan: Satu STUDENT bisa ambil banyak COURSE (One-to-Many). Satu COURSE bisa diambil banyak STUDENT (One-to-Many). ENROLLMENT adalah tabel junction (bridge) yang menghubungkan keduanya.

📋 BEST PRACTICE

Normalisasi Database (1NF, 2NF, 3NF)

Normalisasi = Proses menghilangkan redundansi data untuk membuat database lebih efisien.

❌ Tabel TIDAK Normal:

students: id, name, courses (berisi: "Math, Science, English")

🔴 Masalah: Kolom courses menyimpan multiple values (tidak atomik). Sulit dicari dan dimodifikasi.

✅ Tabel NORMAL (1NF, 2NF, 3NF):

students: id, name

enrollments: id, student_id, course_id

🟢 Solusi: Pisahkan ke tabel terpisah. Setiap kolom atomic (1 value saja). Lebih fleksibel & cepat.

Rule of Thumb: Jika kamu melihat kolom yang berisi multiple values (dipisah koma atau array), itu tanda untuk split ke tabel baru!

🔗 RELASI DATABASE

Relasi One-to-One (1:1)

Satu record di tabel A berhubungan dengan SATU record di tabel B, dan sebaliknya.

👤

User

id, username, email

🪪

Profile

id, user_id (FK), bio, avatar

Analogi: Satu orang = satu KTP. Satu KTP hanya milik satu orang.

laravel/database/migrations/create_profiles_table.php
Schema::create('profiles', function (Blueprint $table) { $table->id(); $table->foreignId('user_id')->unique()->constrained(); $table->text('bio')->nullable(); $table->string('avatar')->nullable(); $table->timestamps(); });

💡 Catatan: ->unique() pada foreign key memastikan One-to-One (tidak bisa ada 2 profiles untuk 1 user).

🔗 RELASI DATABASE

Relasi One-to-Many (1:N)

Satu record di tabel A berhubungan dengan BANYAK record di tabel B.

🏪

Category

id, name

📦 Product 1

📦 Product 2

📦 Product N

Analogi: Satu rak toko punya banyak produk. Satu kategori "Makanan" punya ratusan produk, tapi setiap produk cuma di 1 kategori.

app/Models/Category.php
public function products() { return $this->hasMany(Product::class); }

💡 Di Laravel, gunakan hasMany() untuk relasi One-to-Many!

🔗 RELASI DATABASE

Relasi Many-to-Many (N:M)

Banyak record di tabel A berhubungan dengan BANYAK record di tabel B.

👨‍🎓 Student 1

👨‍🎓 Student 2

👨‍🎓 Student N

📚 Course 1

📚 Course 2

📚 Course M

Analogi: Satu siswa bisa ambil banyak course. Satu course bisa diambil banyak siswa. Dibutuhkan tabel "junction" (tabel penengah) untuk menghubungkan keduanya!

app/Models/Student.php
public function courses() { return $this->belongsToMany(Course::class); }

✨ Laravel otomatis handle junction table (enrollments) di belakang layar dengan belongsToMany()!

⚙️ SETUP

Konfigurasi Database di Laravel

Sebelum membuat tabel, setup koneksi database di file .env

.env
# Database Connection DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=belajar_web_db DB_USERNAME=root DB_PASSWORD= # Pastikan MySQL sudah running di komputer!

Setelah itu, test koneksi dengan command:

Terminal
php artisan tinker >>> DB::connection()->getPDO(); # Jika tidak error, koneksi berhasil! ✅

💡 Catatan: Pastikan nama database sudah dibuat di MySQL. Gunakan MySQL Workbench atau phpMyAdmin untuk membuat database baru!

📂 FILE GENERATOR

Migration — Versioning untuk Database

Migration adalah file yang mendefinisikan struktur tabel. Seperti Git untuk database, tapi untuk schema!

Terminal
# Generate file migration baru php artisan make:migration create_products_table

File akan dibuat di database/migrations/:

database/migrations/2024_06_06_create_products_table.php
public function up() { Schema::create('products', function (Blueprint $table) { $table->id(); $table->string('name'); $table->decimal('price', 10, 2); $table->timestamps(); }); } public function down() { Schema::dropIfExists('products'); }

Jalankan migration:

Terminal
php artisan migrate

✨ Tabel products akan otomatis terbuat di MySQL!

🌱 DATA GENERATION

Seeder & Factory — Semai Data Dummy

Analogi: Seeder seperti menanam benih, Factory seperti mesin pemotong yang membuat design seragam sebelum ditanam.

1️⃣ Generate Factory

Terminal
php artisan make:factory ProductFactory --model=Product

2️⃣ Setup Factory (database/factories/ProductFactory.php)

ProductFactory.php
public function definition() { return [ 'name' => $this->faker->word(), 'price' => $this->faker->numberBetween(10000, 100000), ]; }

3️⃣ Generate Seeder

Terminal
php artisan make:seeder ProductSeeder

4️⃣ Jalankan Seeder (database/seeders/ProductSeeder.php)

ProductSeeder.php
Product::factory()->count(50)->create(); # Tara! 50 produk dummy terbuat!

Jalankan dengan: php artisan db:seed --class=ProductSeeder

🔮 ORM

Eloquent ORM — CRUD Operasi

Eloquent adalah "magic tool" Laravel yang bikin kita menulis query pakai PHP objects, bukan raw SQL!

🟢 CREATE — Insert Data Baru

Create
$product = new Product(); $product->name = 'Laptop Gaming'; $product->price = 15000000; $product->save(); // Atau shortcut: Product::create([ 'name' => 'Laptop Gaming', 'price' => 15000000 ]);

🔵 READ — Query Data

Read
// Ambil semua $products = Product::all(); // Ambil by ID $product = Product::find(1); // Ambil dengan kondisi $expensive = Product::where('price', '>', 10000000)->get();

🟡 UPDATE — Ubah Data

Update
$product = Product::find(1); $product->price = 12000000; $product->save(); // Atau shortcut: Product::where('id', 1)->update(['price' => 12000000]);

🔴 DELETE — Hapus Data

Delete
$product = Product::find(1); $product->delete(); // Atau langsung: Product::destroy(1);
⚡ OPTIMIZATION

Eager Loading vs Lazy Loading

Analogi kehidupan sehari-hari:

❌ LAZY LOADING (Berbelanja Satu Per Satu)

Seperti kamu pergi ke supermarket untuk beli 100 barang, tapi tiap barang harus naik ke mobil dan kembali. 101 perjalanan!

Trip 1: Get 100 Products
⬇️
Loop 1 → Get Category 1 (Trip 2)
Loop 2 → Get Category 2 (Trip 3)
Loop 3 → Get Category 3 (Trip 4)
... Loop 100 → Get Category 100 (Trip 101)
⬇️
⏱️ Total: 101 DATABASE HITS (LAMBAT!)

✅ EAGER LOADING (Pakai Keranjang Belanja Besar)

Kamu masukkan semua 100 barang dalam 1 keranjang besar, cuma 2 perjalanan total! Masuk aja sekali bawa semuanya.

Trip 1: Get 100 Products
⬇️
Trip 2: Get ALL Categories (WHERE id IN [1,2,3...,100])
⬇️
⚡ Total: 2 DATABASE HITS (CEPAT!)

📊 Tabel Perbandingan Query Performance:

Aspek ❌ Lazy Loading ✅ Eager Loading
Jumlah Query N + 1 (banyak!) 1 + 1 = 2 (minimal)
Waktu Eksekusi ~500ms - 5s (lambat) ~10ms - 100ms (cepat)
Beban Database Tinggi (banyak koneksi) Rendah (sedikit koneksi)
Scalability Buruk (melambat saat data besar) Baik (performa stabil)
Contoh Kasus Ambil 100 products, loop akses category Ambil 100 products + categories sekaligus

💻 Kode Perbandingan:

❌ LAZY LOADING (Buruk)

Lazy Loading (N+1 Problem)
$products = Product::all(); // Query 1: SELECT * FROM products foreach ($products as $product) { echo $product->category->name; // Query 2, 3, 4, ... (N+1!) // SELECT * FROM categories WHERE id = 1 // SELECT * FROM categories WHERE id = 2 // ... 100 kali! }

✅ EAGER LOADING (Bagus!)

Eager Loading (Efficient)
// Pakai ->with('category') untuk eager load $products = Product::with('category')->get(); // Query 1: SELECT * FROM products // Query 2: SELECT * FROM categories WHERE id IN (1, 2, 3, ..., 100) foreach ($products as $product) { echo $product->category->name; // Langsung ambil dari memory, TIDAK ADA QUERY LAGI! }

💡 GOLDEN RULE: Setiap kali akses relasi (->category, ->products, dll), WAJIB pakai ->with() untuk eager load!

🔨 QUERY

Query Builder — Konstruksi Query Kompleks

Query Builder memudahkan menulis query kompleks tanpa raw SQL:

Query Builder Methods
// SELECT Product::select('name', 'price') // WHERE (filter) ->where('price', '>', 100000) ->where('stock', '>', 0) // JOIN (relasi) ->join('categories', 'products.category_id', '=', 'categories.id') // ORDER BY (urutan) ->orderBy('price', 'desc') // GROUP BY (grouping) ->groupBy('category_id') // AGGREGATE (hitung) ->count() // atau sum(), avg(), min(), max() // LIMIT (batasi) ->limit(10)->get();

Contoh Kompleks:

Contoh Query
// Ambil 10 produk mahal di kategori "Electronics" diurutkan dari paling mahal $products = Product::where('category', 'Electronics') ->where('price', '>', 5000000) ->orderBy('price', 'desc') ->limit(10) ->get();
🏛️ ARCHITECTURE

Arsitektur Lengkap: MVC + Database

Flowchart bagaimana request user sampai ke database dan kembali:

graph TD A["👤 User Browser"] -->|1. HTTP Request| B["⚙️ Web Server
Routing"] B -->|2. Route Match| C["🎮 Controller
ProductController"] C -->|3. Call Model| D["🗂️ Model/ORM
Product::find"] D -->|4. Query| E["🗄️ Database
MySQL"] E -->|5. Result| D D -->|6. Eloquent Object| C C -->|7. Data to View| F["🎨 View/Template
products/show.blade.php"] F -->|8. HTML Response| A

📋 Tabel Alur Request-Response:

🔢 Step Komponen 🎯 Tugas 📤 Input 📥 Output
1 Browser User klik link atau submit form User action (click) HTTP Request (GET/POST/PUT/DELETE)
2 Router Cocokkan URL dengan route yang didefinisikan Request URL (e.g., /products/1) Nama Controller & Method
3 Controller Jalankan logika bisnis, siapkan data Route parameters, Form data Call Model method, siapkan response
4 Model Akses database, query, relasi data Query parameters, filter Eloquent Collection atau Model instance
5 Database Eksekusi SQL query, return result set SQL query (SELECT, INSERT, UPDATE, DELETE) Result set dari tabel database
6 Model Convert result ke PHP object/collection Raw database result Eloquent Model instance
7 Controller Pass data ke view untuk rendering Data dari model View file dengan data
8 View (Blade) Render HTML dengan data dinamis Data dari controller HTML string
9 Browser Tampilkan HTML di layar user HTTP Response (HTML) Halaman web yang terlihat

🎯 Konsep Kunci:

  • Routes/web.php: Tentukan URL endpoint dan mapping ke Controller
  • Controller: Logika aplikasi (validasi, transform, orchestrate)
  • Model: Interaksi langsung ke database & relasi data
  • View (Blade): Template HTML yang di-render dengan data dinamis
  • Database: Simpan data persistently (permanen)

✨ Separation of Concerns: Setiap layer punya tanggung jawab tersendiri! Gampang dimaintain & scalable.

🚀 PROJECT

Mini Project: Product Management System

Wireframe animasi dari aplikasi yang akan kamu bangun:

📋 Fitur Wajib:

  • Dashboard: List semua produk dalam tabel
  • Create: Form tambah produk baru + upload gambar
  • Edit: Form ubah data produk + ganti gambar
  • Delete: Hapus produk dengan konfirmasi
  • Search: Pencarian produk by nama/kategori
  • Filter: Filter by kategori + harga range
  • Database Relasi: Products ↔ Categories (One-to-Many)

🏗️ Struktur Tabel:

Database Schema
-- categories table id, name, slug, description, created_at -- products table id, category_id (FK), name, slug, description, price, stock, image_path, created_at, updated_at

🎯 User Story:

"Sebagai admin toko online, saya ingin CRUD produk dengan mudah, upload gambar, dan organize produk by kategori agar customer bisa cari produk yang mereka mau."

📊 RECAP

Ringkasan BAB 9 — Mind Map

mindmap root((DATABASE)) Konsep Table, Row, Column Primary Key Foreign Key Index Design ERD Normalisasi (1NF, 2NF, 3NF) Data Integrity Relasi One-to-One One-to-Many Many-to-Many Laravel Migration Seeder & Factory Eloquent ORM Query Builder Optimization Eager Loading Indexes Query Analysis Best Practice ACID Properties Foreign Key Constraints Data Validation

✨ Kombinasi dari semua konsep ini yang membuat aplikasi web professional dan scalable!

📝 LATIHAN 1

Task: Desain ERD Sistem Perpustakaan

Buatlah ERD untuk sistem perpustakaan sekolah dengan ketentuan:

📚 Requirement:

  • Minimal 3 tabel: books, members, loans
  • Tabel books: id, title, author, isbn, published_year, quantity
  • Tabel members: id, name, nim/nis, email, phone, address
  • Tabel loans: id, member_id (FK), book_id (FK), loan_date, return_date (nullable), status
  • Relasi: Members 1-to-Many Loans, Books 1-to-Many Loans
  • Identifikasi Primary Key dan Foreign Key di setiap tabel

📋 Deliverable:

  • 1 file ERD (bisa pakai Lucidchart, Draw.io, atau Mermaid)
  • Jelaskan relasi antar tabel
  • Screenshot atau diagram dalam format gambar/PDF

💡 Hint: Satu member bisa pinjam banyak buku. Satu buku bisa dipinjam banyak member (tapi beda waktu)!

📝 LATIHAN 2

Task: Migration & Seeder untuk Product-Category

Buatlah migration dan seeder untuk sistem product-category di Laravel:

📂 Step-by-Step:

  • Generate 2 migration: categories dan products
  • Tabel categories: id, name, slug, description, created_at, updated_at
  • Tabel products: id, category_id (FK), name, slug, description, price (decimal), stock (integer), created_at, updated_at
  • Generate ProductFactory dengan faker untuk name, price (10k-100k), stock (1-100)
  • Generate CategorySeeder: buat 5 kategori (Electronics, Clothing, Books, Food, Sports)
  • Generate ProductSeeder: buat 30 produk dengan random category_id
  • Jalankan: php artisan migrate --seed

📋 Deliverable:

  • File migration (2 files)
  • File factory (1 file)
  • File seeder (2 files)
  • Screenshot MySQL Workbench/phpMyAdmin menunjukkan data yang ter-seed

✨ Verified: Semua data muncul di database tanpa error!

🏆 FINAL PROJECT

Tugas Akhir: Product Management System

Bangun aplikasi web LENGKAP dengan fitur:

🎯 Core Features:

  • CRUD Produk: Create, Read, Update, Delete products
  • CRUD Kategori: Manage categories
  • Relasi Database: Products belong to Category (One-to-Many)
  • Upload Gambar: File upload untuk product image (store di storage/)
  • Search & Filter: Cari produk by nama, filter by kategori/harga
  • Validation: Validasi input di form (required, email, numeric, dll)
  • UI/UX: Bootstrap/Tailwind untuk styling responsive
  • Database Transaction: Pastikan data integrity (pakai ->transaction())

📝 File Structure yang Wajib:

Laravel Project Structure
app/Models/ - Product.php (dengan relasi category) - Category.php (dengan relasi products) app/Http/Controllers/ - ProductController.php - CategoryController.php database/migrations/ - *_create_categories_table.php - *_create_products_table.php resources/views/ - products/index.blade.php - products/create.blade.php - products/edit.blade.php - categories/... (similar) routes/web.php (define routes)

🚀 Deliverable:

  • Push ke GitHub (atau submit folder project)
  • README.md dengan cara install & setup
  • Screenshot aplikasi running (dashboard, form create, form edit, delete dengan modal confirm)
  • Video demo 2 menit (atau GIF) menunjukkan fitur CRUD, upload gambar, search/filter working

🎊 Selesaikan project ini = kamu sudah mahir Database + Laravel! Siap untuk mini project atau internship! 🎊

Slide 1 / 22